package com.ceair.flight.refund.service.uatp.impl;


import com.ceair.flight.refund.dto.appmoblie.RefundApplyDto;
import com.ceair.flight.refund.dto.external.BasePageQueryReq;
import com.ceair.flight.refund.dto.uatp.BasicRes;
import com.ceair.flight.refund.dto.uatp.CardForRefundNoQueryRes;
import com.ceair.flight.refund.dto.uatp.QueryCardForRefundNo;
import com.ceair.flight.refund.dto.uatp.ResponseConstants;
import com.ceair.flight.refund.dto.uatp.request.CardForRefundNo;
import com.ceair.flight.refund.location.dao.IRefundApplyDao;
import com.ceair.flight.refund.location.dt.enums.RefundStatus;
import com.ceair.flight.refund.location.dt.enums.RefundStatusEnum;
import com.ceair.flight.refund.service.notification.IUatpRefundNotification;
import com.ceair.flight.refund.service.uatp.IApplyQuery;
import com.ceair.flight.refund.service.uatp.IGenRefNoService;
import com.ceair.flight.refund.service.uatp.IRefundPayUATPservice;
import com.ceair.flight.refund.util.Base64Util;
import com.ceair.flight.refund.util.GsonUtil;
import com.ceair.muservice.common.dto.page.PaginationResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.*;

@Service("refundPayUATPService")
@Path("/")
public class IRefundPayUATPserviceImpl implements IRefundPayUATPservice {
    private static final Logger LOG = LoggerFactory.getLogger(IRefundPayUATPserviceImpl.class);
    private static final RefundStatus[] STATUS_AFTER_REFUND_FORM = {RefundStatus.SECOND_AUDIT_PASS, RefundStatus.WAITING_CARD_FOR_REFUND_NO, RefundStatus.WAIT_MONEY_REFUND, RefundStatus.MONEY_REFUNDING, RefundStatus.MONEY_REFUND_EXCEPTION, RefundStatus.MONEY_REFUND_SUCCESS, RefundStatus.REFUNDED_DONE};

    @Resource(name = "facadeRefundApplyQueryImpl")
    private IApplyQuery applyQuery;

    @Autowired
    private IGenRefNoService genRefNoService;

    @Autowired
    private IRefundApplyDao applyDao;

    @Resource(name = "uatpRefundNotification")
    private IUatpRefundNotification uatpRefundNotification;

    @Override
    @POST
    @Path("/getUatpPayRefundList")
    @Consumes({"application/json"})
    @Produces(MediaType.APPLICATION_JSON)
    public CardForRefundNoQueryRes getUatpPayRefundList(String encryptStr) {
        LOG.info("UATP request {}", encryptStr);
        CardForRefundNoQueryRes result = new CardForRefundNoQueryRes();
        QueryCardForRefundNo request = parseRequestInfo(encryptStr);
        if (request == null) {
            result.setCode(ResponseConstants.CODE_INALID_REQUEST);
            return result;
        }
        List<RefundApplyDto> applyList = getUatpList(request.getFlightOrderNo(), RefundStatus.SECOND_AUDIT_PASS, RefundStatus.WAITING_CARD_FOR_REFUND_NO);
        if (applyList != null && applyList.size() > 0) {
            result.setResult(applyList);
            result.setCode(ResponseConstants.CODE_SUCCESS);
        } else {
            result.setCode(ResponseConstants.CODE_DONE);
        }
        return result;
    }

    @Override
    @POST
    @Path("/generateUATPRefundFormNo")
    @Consumes({"application/json"})
    @Produces(MediaType.APPLICATION_JSON)
    public BasicRes generateRefundFormNo(CardForRefundNo cardForRefundNo) {
        BasicRes result = new BasicRes();
        String applyInfo = cardForRefundNo.getApplyInfo();
        QueryCardForRefundNo requestInfo = parseRequestInfo(applyInfo);
        if (requestInfo == null) {
            result.setCode(ResponseConstants.CODE_INALID_REQUEST);
            return result;
        }
        String flightOrderNo = requestInfo.getFlightOrderNo();
        String cardNo = cardForRefundNo.getCardNo();
        List<RefundApplyDto> uatpList = getUatpList(flightOrderNo, STATUS_AFTER_REFUND_FORM);
        if (uatpList == null || uatpList.isEmpty()) {
            result.setCode(ResponseConstants.CODE_INALID_REQUEST);
            return result;
        }

        boolean success = true;
        int dealSize = 0;
        try {
            for (RefundApplyDto uatpRefund : uatpList) {
                long id = uatpRefund.getId();
                String ticketNo = uatpRefund.getTicketNo();
                String status = uatpRefund.getStatus();
                if (RefundStatusEnum.SECOND_AUDIT_PASS == RefundStatusEnum.getByCode(status) || RefundStatusEnum.WAITING_CARD_FOR_REFUND_NO == RefundStatusEnum.getByCode(status)) {
                    LOG.info("Generating refund form No for refund apply: {} ticketNo: {}", id, ticketNo);
                    boolean isSuccess = genRefNoService.doGenRefNo(uatpRefund.getId(), cardNo);
                    success = success && isSuccess;
                    dealSize++;
                }
            }
        } catch (Exception ex) {
            LOG.error("Genreate UATP refund form NO error", ex);
            success = false;
        }

        if (success && dealSize == uatpList.size()) {
            result.setCode(ResponseConstants.CODE_SUCCESS);
        } else if (!success) {
            result.setCode(ResponseConstants.CODE_INCORRECT_CARD);
        } else if (dealSize == 0) {
            result.setCode(ResponseConstants.CODE_DONE);
        }
        return result;
    }

    @Override
    @POST
    @Path("/sendNotification")
    @Consumes({"application/json"})
    @Produces(MediaType.APPLICATION_JSON)
    public BasicRes sendNotification(long refundApplyId) {
        BasicRes res = new BasicRes();
        boolean uatpRes = false;
        try{
            RefundApplyDto applyDto = applyDao.getRefundApplyDto(refundApplyId);
            if (null != applyDto){
                uatpRes = uatpRefundNotification.sendNotification(applyDto);
            }else {
                res.setCode("000X3");
                res.setMsg("UATP发送通知异常，原因：没有找到对应退票单");
            }
        }catch (Exception e){
            LOG.error("refundApplyId:" + refundApplyId + " UATP消息通知异常：" + e);
            res.setCode("000X1");
            res.setMsg("UATP发送通知异常，原因：" + e.getMessage());
            return res;
        }
        if (uatpRes){
            res.setCode("0");
            res.setMsg("success");
        }else {
            res.setCode("000X2");
            res.setMsg("UATP消息通知失败");
        }
        return res;
    }

    private List<RefundApplyDto> getUatpList(String flightOrderNo, RefundStatus... statuses) {
        BasePageQueryReq queryReq = new BasePageQueryReq();
        queryReq.setPagination(false);
        queryReq.setFlightOrderNo(flightOrderNo);
        Set<RefundStatus> refundslist = new HashSet<>(Arrays.asList(statuses));
        queryReq.setRefundslist(refundslist);
        PaginationResult<RefundApplyDto> applyResult = applyQuery.getList(queryReq);
        List<RefundApplyDto> applyList = applyResult.getData();
        return applyList;
    }

    private QueryCardForRefundNo parseRequestInfo(String encryptStr) {
        try {
            String decryptInfo = Base64Util.decode(encryptStr);
            LOG.info("UATP request info after decrypted value is {}", decryptInfo);
            QueryCardForRefundNo requestEntity = GsonUtil.fromJson(decryptInfo, QueryCardForRefundNo.class);
            requestEntity.check();
            LOG.info("The request entity for generating refund form No is: {}", requestEntity);
            return requestEntity;
        } catch (Exception e) {
            LOG.error("Parsing encrypt detail error or convert to request entity error", e);
        }
        return null;
    }
}
